/**
 * 
 */
package com.hu.ta.assignment5.application;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import com.hu.ta.assignment5.beans.AnnotatedText;
import com.hu.ta.assignment5.beans.PosTagger;
import com.hu.ta.assignment5.evaluation.ComparisonResults;
import com.hu.ta.assignment5.io.FileIO;
import com.hu.ta.assignment5.io.FilePos;
import com.hu.ta.assignment5.io.FileTxt;
import com.hu.ta.assignment5.ui.UIBuilder;
import com.hu.ta.assignment5.util.ConfigurationUtils;

/**
 * Logic unit of the application
 * 
 * @author cage@g.com
 */

public class Controller {

	private UIBuilder ui;
	private FileIO connections;
	private ConfigurationUtils configuration;
	private PosTagger evalTagger;

	public Controller() {
		super();
		configuration = ConfigurationUtils.getInstance();
		ui = new UIBuilder(this);
	}

	private static boolean isUsableFile(File file) {
		return file.getName().startsWith("c") && file.isFile();
	}

	public void startProgram() {
		loadConfiguration();
		ui.startUI();

		// Training
		if (configuration.IsLearning()) {
			learn(false, new File(configuration.getInputFolder()).listFiles());
		} else {
			doTagging(false,
					new File(configuration.getInputFolder()).listFiles());
		}
		ui.update(null, "Finished!");
	}

	public File[] getInputFiles() {
		return new File(configuration.getInputFolder()).listFiles();
	}

	public void doEvaluation(int numParts) {
		loadConfiguration();
		ui.startUI();

		File allFiles[] = getInputFiles();

		for (int part = 0; part < numParts; part++) {
			ComparisonResults res = new ComparisonResults(0, 0);
			int num = 0;
			List<File> trainFiles = new ArrayList<File>();
			List<File> evalFiles = new ArrayList<File>();
			for (File file : allFiles) {
				if (num >= ((float) allFiles.length / numParts) * part
						&& num < ((float) allFiles.length / numParts)
								* (part + 1)) {
					evalFiles.add(file);
				} else {
					trainFiles.add(file);
				}
				num++;
			}

			learn(true, trainFiles.toArray(new File[trainFiles.size()]));
			FileTxt taggedFiles[] = doTagging(true,
					evalFiles.toArray(new File[evalFiles.size()]));

			int i = 0;
			for (File file : evalFiles) {
				FileIO txt = new FileTxt(file.getAbsolutePath());
				txt.read();
				res.add(((FileTxt) txt).getText().compareTo(
						taggedFiles[i++].getText()));
			}

			ui.update(null, "Tokens overall: " + res.getNum()
					+ "\nWrong POS tags: " + res.getWrong() + "\n");
		}

		ui.update(null, "Finished!");
	}

	private void learn(boolean bEvaluation, File files[]) {
		int i = 0;
		ArrayList<FileIO> trains = new ArrayList<FileIO>();

		for (File txt : files) {
			if (isUsableFile(txt)) {
				FileIO f = new FileTxt(txt.getAbsolutePath());
				f.read();
				trains.add(f);
				// System.out.println("File " + ++i + " trained");
			}
		}

		PosTagger tagger = new PosTagger();
		tagger.train(trains);

		if (!bEvaluation) {
			connections = new FilePos(configuration.getTrainedDataFile());
			((FilePos) connections).setTagger(tagger);
			connections.write();
		} else {
			this.evalTagger = tagger;
		}
	}

	private FileTxt[] doTagging(boolean bEvaluation, File files[]) {
		PosTagger tagger;
		if (!bEvaluation) {
			connections = new FilePos(configuration.getTrainedDataFile());
			connections.read();
			tagger = ((FilePos) connections).getTagger();
		} else {
			tagger = this.evalTagger;
		}

		FileTxt outputFiles[] = new FileTxt[files.length];
		int i = 0;
		for (File txt : files) {
			if (isUsableFile(txt)) {
				connections = new FileTxt(txt.getAbsolutePath());
				connections.read();
				AnnotatedText text = connections.getText();

				text = tagger.tag(text);

				File path = new File(configuration.getOutputFolder()
						+ txt.getName() + ".pos");
				connections = new FileTxt(path.getAbsolutePath());
				connections.setText(text);
				connections.write();
				outputFiles[i++] = (FileTxt) connections;
			}
		}
		return outputFiles;
	}

	private void loadConfiguration() {
		// Given task: set only the source directory/no config file --> nothing
		// to do
	}
}
